home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
New Star Software Collection
/
NSS_Collection.iso
/
3-004 ms visual basic pro 30
/
4.imz
/
4.IMA
/
CIRC3.C_
/
CIRC3.bin
Wrap
Text File
|
1993-04-28
|
24KB
|
845 lines
//---------------------------------------------------------------------------
// Copyright (C) 1991-93, Microsoft Corporation
//
// You have a royalty-free right to use, modify, reproduce and distribute
// the Sample Custom Control Files (and/or any modified version) in any way
// you find useful, provided that you agree that Microsoft has no warranty,
// obligation or liability for any Custom Control File.
//---------------------------------------------------------------------------
// Circ3.c
//---------------------------------------------------------------------------
// Contains control procedure for CIRC3 control
//---------------------------------------------------------------------------
#include <windows.h>
#include <vbapi.h>
#include <string.h>
#include "circ3.h" // Declares Vb3.0 compatable model information
#include "circ3vb2.h" // Declares Vb2.0 compatable model information
#include "circ3vb1.h" // Declares Vb1.0 compatable model information
//---------------------------------------------------------------------------
// Local Prototypes
//---------------------------------------------------------------------------
VOID NEAR PaintCircle(HCTL hctl, HWND hwnd, HDC hdc);
VOID NEAR RecalcArea(HCTL hctl, HWND hwnd);
VOID NEAR FlashCircle(HCTL hctl, HDC hdc);
BOOL NEAR InCircle(HCTL hctl, SHORT xcoord, SHORT ycoord);
VOID NEAR FireClickIn(HCTL hctl, HWND hwnd, SHORT x, SHORT y);
VOID NEAR FireClickOut(HCTL hctl);
HWND NEAR HwndInitFlashPopup(VOID);
VOID NEAR DisplayHelpTopic(CHAR chKeylist, LPSTR lpszKeyword);
BOOL _export FAR PASCAL FlashDlgProc(HWND hDlg, USHORT msg, USHORT wp, LONG lp);
//---------------------------------------------------------------------------
// Global Variables
//---------------------------------------------------------------------------
HANDLE hmodDLL;
WORD cVbxUsers = 0;
BOOL fDevTimeInited = FALSE;
//---------------------------------------------------------------------------
// Global Variables for FlashColor dialog
//---------------------------------------------------------------------------
BOOL fDlgInUse = FALSE;
HCTL hctlDialog;
USHORT ipropDialog;
LONG colorOldDialog;
//---------------------------------------------------------------------------
// Circle Control Procedure
//---------------------------------------------------------------------------
LONG FAR PASCAL _export CircleCtlProc
(
HCTL hctl,
HWND hwnd,
USHORT msg,
USHORT wp,
LONG lp
)
{
switch (msg)
{
case VBM_DATA_AVAILABLE:
{
ERR err;
HSZ hszFieldName;
LONG lData;
LPDATAACCESS lpda;
lpda = (LPDATAACCESS)lp;
switch (lpda->sAction) {
case DATA_CLOSE:
case DATA_DELETE:
case DATA_UNLOAD:
VBSetControlFlags(hctl, CTLFLG_DATACHANGED, 0L);
return 0;
default:
break;
}
err = (ERR)VBGetControlProperty(hctl, IPROP_CIRCLE_DATAFIELD, &hszFieldName);
if (err)
return err;
if (!hszFieldName || *VBDerefHsz(hszFieldName) == 0) {
if (hszFieldName)
VBDestroyHsz(hszFieldName);
return 0;
}
lpda->hszDataField = hszFieldName;
lpda->sAction = DATA_FIELDVALUE;
lpda->usDataType = DT_HSZ;
lpda->lData = NULL;
err = (ERR)VBSendControlMsg(lpda->hctlData, VBM_DATA_GET, 0, (LONG)lpda);
if (err || !lpda->lData) {
VBDestroyHsz(hszFieldName);
return err;
}
lData = (LONG)VBLockHsz((HSZ)lpda->lData);
VBSetControlFlags(hctl, CTLFLG_DATACHANGED, 0L);
VBSetControlFlags(hctl, CTLFLG_BOUNDDATASET, CTLFLG_BOUNDDATASET);
err = VBSetControlProperty(lpda->hctlBound, IPROP_CIRCLE_CAPTION, lData);
VBSetControlFlags(hctl, CTLFLG_BOUNDDATASET, 0L);
VBUnlockHsz((HSZ)lpda->lData);
VBDestroyHsz(hszFieldName);
VBDestroyHsz((HSZ)lpda->lData);
return err;
}
case VBM_DATA_REQUEST:
{
ERR err;
HSZ hszCaption;
HSZ hszFieldName;
LPDATAACCESS lpda;
lpda = (LPDATAACCESS)lp;
if (!(VBSetControlFlags(hctl, 0L, 0L) & CTLFLG_DATACHANGED))
return 0;
err = (ERR)VBGetControlProperty(hctl, IPROP_CIRCLE_DATAFIELD, &hszFieldName);
if (err)
return err;
if (!hszFieldName || *VBDerefHsz(hszFieldName) == 0) {
if (hszFieldName)
VBDestroyHsz(hszFieldName);
return 0;
}
err = (ERR)VBGetControlProperty(hctl, IPROP_CIRCLE_CAPTION, &hszCaption);
if (err) {
VBDestroyHsz(hszFieldName);
return err;
}
lpda->hszDataField = hszFieldName;
lpda->sAction = DATA_FIELDVALUE;
lpda->usDataType = DT_HSZ;
lpda->lData = hszCaption;
err = (ERR)VBSendControlMsg(lpda->hctlData, VBM_DATA_SET, 0, (LONG)lpda);
if (!err)
VBSetControlFlags(hctl, CTLFLG_DATACHANGED, 0L);
VBDestroyHsz(hszFieldName);
VBDestroyHsz(hszCaption);
return err;
}
case WM_NCCREATE:
{
LPCIRC lpcirc = (LPCIRC)VBDerefControl(hctl);
lpcirc->CircleShape = SHAPE_CIRCLE;
lpcirc->FlashColor = 128L;
VBSetControlProperty(hctl, IPROP_CIRCLE_BACKCOLOR, 255L);
// *** lpcirc may now be invalid due to call to VB API ***
break;
}
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
if (InCircle(hctl, (SHORT)lp, (SHORT)HIWORD(lp)))
{
HDC hdc = GetDC(hwnd);
FlashCircle(hctl, hdc);
ReleaseDC(hwnd, hdc);
FireClickIn(hctl, hwnd, (SHORT)lp, (SHORT)HIWORD(lp));
}
else
FireClickOut(hctl);
break;
case WM_LBUTTONUP:
if (InCircle(hctl, (SHORT)lp, (SHORT)HIWORD(lp)))
{
HDC hdc = GetDC(hwnd);
PaintCircle(hctl, hwnd, hdc);
ReleaseDC(hwnd, hdc);
}
break;
case WM_SETFONT:
LpcircDEREF(hctl)->hfont = (HFONT)wp;
return 0;
case WM_GETFONT:
return LpcircDEREF(hctl)->hfont;
case WM_SETTEXT:
{
HSZ hsz;
LPCIRC lpcirc = LpcircDEREF(hctl);
if (lpcirc->hszCaption)
{
VBDestroyHsz(lpcirc->hszCaption);
// *** lpcirc may now be invalid due to call to VB API ***
}
hsz = VBCreateHsz((_segment)hctl, (LPSTR)lp);
// *** lpcirc may now be invalid due to call to VB API ***
LpcircDEREF(hctl)->hszCaption = hsz;
InvalidateRect(hwnd, NULL, TRUE);
return 0L;
}
case WM_GETTEXT:
{
LPSTR lpstr;
USHORT cch;
LPCIRC lpcirc = LpcircDEREF(hctl);
if (lpcirc->hszCaption == NULL)
{
*(LPSTR)lp = 0L;
wp = 1;
}
else
{
lpstr = VBDerefHsz(lpcirc->hszCaption);
cch = (USHORT)(lstrlen(lpstr) + 1);
if (wp > cch)
wp = cch;
_fstrncpy((LPSTR)lp, lpstr, wp);
((LPSTR)lp)[wp - 1] = '\0';
}
}
return (LONG)(wp - 1);
case WM_GETTEXTLENGTH:
{
LPCIRC lpcirc = LpcircDEREF(hctl);
if (lpcirc->hszCaption == NULL)
return 0L;
else
return lstrlen(VBDerefHsz(lpcirc->hszCaption));
}
case WM_PAINT:
if (wp)
PaintCircle(hctl, hwnd, (HDC)wp);
else
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
PaintCircle(hctl, hwnd, ps.hdc);
EndPaint(hwnd, &ps);
}
break;
case WM_SIZE:
RecalcArea(hctl, hwnd);
break;
case VBM_SETPROPERTY:
switch (wp)
{
case IPROP_CIRCLE_CIRCLESHAPE:
LpcircDEREF(hctl)->CircleShape = (ENUM)lp;
RecalcArea(hctl, hwnd);
InvalidateRect(hwnd, NULL, TRUE);
return 0L;
case IPROP_CIRCLE_CAPTION:
VBSetControlFlags(hctl, CTLFLG_DATACHANGED, CTLFLG_DATACHANGED);
}
break;
case VBM_HELP:
switch (LOBYTE(wp))
{
case VBHELP_PROP:
// High byte identifies which property.
// Keyword is: "<property>"
switch (HIBYTE(wp))
{
case IPROP_CIRCLE_CIRCLESHAPE:
DisplayHelpTopic('P', "CircleShape");
return 0L;
case IPROP_CIRCLE_FLASHCOLOR:
DisplayHelpTopic('P', "FlashColor");
return 0L;
}
break;
case VBHELP_EVT:
// High byte identifies which event
// Keyword is: "<event>"
switch (HIBYTE(wp))
{
case IEVENT_CIRCLE_CLICKIN:
DisplayHelpTopic('V', "ClickIn");
return 0L;
case IEVENT_CIRCLE_CLICKOUT:
DisplayHelpTopic('V', "ClickOut");
return 0L;
}
break;
case VBHELP_CTL:
// High byte is unused.
// Keyword is: "<classname>"
DisplayHelpTopic('C', "CIRC3");
return 0L;
}
break;
case VBM_INITPROPPOPUP:
switch (wp)
{
// Un-commenting the following line will enable our custom
// popup instead of the color palette, when setting the
// backcolor:
// case IPROP_CIRCLE_BACKCOLOR:
case IPROP_CIRCLE_FLASHCOLOR:
{
if (fDlgInUse)
// Our dialog is already in use, so return NULL here
// to avoid bringing up a 2nd instance of the dialog.
// We could get around this restriction by storing
// hctlDialog, ipropDialog, and colorOldDialog as
// window words of hwndPopup.
// NOTE: In this specific case, because FlashColor
// is DT_COLOR, we could also just "break;" to go
// through default processing which would bring up
// the default color palette.
return NULL;
// Tell the hwndPopup which control and iprop we want
// the dialog to change
fDlgInUse = TRUE;
hctlDialog = hctl;
ipropDialog = wp;
return HwndInitFlashPopup();
}
}
break;
}
return VBDefControlProc(hctl, hwnd, msg, wp, lp);
}
//---------------------------------------------------------------------------
// Handle painting by drawing circle into the given hdc.
//---------------------------------------------------------------------------
VOID NEAR PaintCircle
(
HCTL hctl,
HWND hwnd,
HDC hdc
)
{
HBRUSH hbr;
HBRUSH hbrOld = NULL;
LPSTR lpstr;
LPCIRC lpcirc = LpcircDEREF(hctl);
LPRECT lprect = &lpcirc->rectDrawInto;
HFONT hfontOld = NULL;
hbr = (HBRUSH)SendMessage(GetParent(hwnd), WM_CTLCOLOR,
hdc, MAKELONG(hwnd, 0));
if (hbr)
hbrOld = SelectObject(hdc, hbr);
Ellipse(hdc, lprect->left, lprect->top, lprect->right, lprect->bottom);
if (lpcirc->hfont)
hfontOld = SelectObject(hdc, lpcirc->hfont);
lpstr = VBDerefHsz(lpcirc->hszCaption);
DrawText(hdc, lpstr, -1, lprect, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
if (hbrOld)
SelectObject(hdc, hbrOld);
if (hfontOld)
SelectObject(hdc, hfontOld);
}
//---------------------------------------------------------------------------
// Paint the circle in the FlashColor.
//---------------------------------------------------------------------------
VOID NEAR FlashCircle
(
HCTL hctl,
HDC hdc
)
{
HBRUSH hbr;
HBRUSH hbrOld = NULL;
LPCIRC lpcirc = LpcircDEREF(hctl);
LPRECT lprect = &lpcirc->rectDrawInto;
hbr = CreateSolidBrush(RGBCOLOR(lpcirc->FlashColor));
if (hbr)
hbrOld = SelectObject(hdc, hbr);
Ellipse(hdc, lprect->left, lprect->top, lprect->right, lprect->bottom);
if (hbr)
{
SelectObject(hdc, hbrOld);
DeleteObject(hbr);
}
}
//---------------------------------------------------------------------------
// Use the hwnd's client size to determine the bounding rectangle for the
// circle. If CircleShape is TRUE, then we need to calculate a square
// centered in lprect.
//---------------------------------------------------------------------------
VOID NEAR RecalcArea
(
HCTL hctl,
HWND hwnd
)
{
LPCIRC lpcirc = LpcircDEREF(hctl);
LPRECT lprect = &lpcirc->rectDrawInto;
GetClientRect(hwnd, lprect);
if (lpcirc->CircleShape == SHAPE_OVAL)
return;
if (lprect->right > lprect->bottom)
{
lprect->left = (lprect->right - lprect->bottom) / 2;
lprect->right = lprect->left + lprect->bottom;
}
else if (lprect->bottom > lprect->right)
{
lprect->top = (lprect->bottom - lprect->right) / 2;
lprect->bottom = lprect->top + lprect->right;
}
}
//---------------------------------------------------------------------------
// Return TRUE if the given coordinates are inside of the circle.
//---------------------------------------------------------------------------
BOOL NEAR InCircle
(
HCTL hctl,
SHORT xcoord,
SHORT ycoord
)
{
double a, b;
double x, y;
LPRECT lprect = &LpcircDEREF(hctl)->rectDrawInto;
a = (lprect->right - lprect->left) / 2;
b = (lprect->bottom - lprect->top) / 2;
x = xcoord - (lprect->left + lprect->right) / 2;
y = ycoord - (lprect->top + lprect->bottom) / 2;
return ((x * x) / (a * a) + (y * y) / (b * b) <= 1);
}
//---------------------------------------------------------------------------
// TYPEDEF for parameters to the ClickIn event.
//---------------------------------------------------------------------------
typedef struct tagCLICKINPARMS
{
HLSTR ClickString;
float far *Y;
float far *X;
LPVOID Index;
} CLICKINPARMS;
//---------------------------------------------------------------------------
// Fire the ClickIn event, passing the x,y coords of the click. Also pass
// the current caption of the Circle control, to demonstrate passing strings
// to event procedures.
//---------------------------------------------------------------------------
VOID NEAR FireClickIn
(
HCTL hctl,
HWND hwnd,
SHORT x,
SHORT y
)
{
CLICKINPARMS params;
float xTwips, yTwips;
USHORT cbCaption, err;
char strBuf[20];
xTwips = (float)VBXPixelsToTwips(x);
yTwips = (float)VBYPixelsToTwips(y);
params.X = &xTwips;
params.Y = &yTwips;
cbCaption = (USHORT)GetWindowText(hwnd, strBuf, 20);
params.ClickString = VBCreateHlstr(strBuf, cbCaption);
err = VBFireEvent(hctl, IEVENT_CIRCLE_CLICKIN, ¶ms);
VBDestroyHlstr(params.ClickString);
}
//---------------------------------------------------------------------------
// Fire the ClickOut event.
//---------------------------------------------------------------------------
VOID NEAR FireClickOut
(
HCTL hctl
)
{
VBFireEvent(hctl, IEVENT_CIRCLE_CLICKOUT, NULL);
}
//---------------------------------------------------------------------------
// Use frame variables to "allocate" a MULTIKEYHELP structure to pass to
// WinHelp().
//---------------------------------------------------------------------------
VOID NEAR DisplayHelpTopic
(
CHAR chKeylist,
LPSTR lpszKeyword
)
{
char rgch[100];
MULTIKEYHELP FAR *lpmkh = rgch;
lpmkh->mkSize = sizeof(MULTIKEYHELP) + lstrlen(lpszKeyword);
if (lpmkh->mkSize > sizeof(rgch))
return;
lpmkh->mkKeylist = chKeylist;
lstrcpy((LPSTR)lpmkh->szKeyphrase, lpszKeyword);
WinHelp(GetActiveWindow(), "circ3.hlp", HELP_MULTIKEY, (DWORD)lpmkh);
}
//---------------------------------------------------------------------------
// Create our property popup-window. Since we want to put up a dialog, this
// window never becomes visible. Instead, when asked to become visible, it
// will post a message to itself, remining it to put up our dialog.
//
// NOTE: May return NULL!
//---------------------------------------------------------------------------
HWND NEAR HwndInitFlashPopup
(
VOID
)
{
return CreateWindow(CLASS_FLASHPOPUP, NULL, WS_POPUP,
0, 0, 0, 0, NULL, NULL,
hmodDLL, NULL);
}
//---------------------------------------------------------------------------
// We asked to show ourself, remain invisible and post a CM_OPENFLASHDLG to
// ourself. When we receive this message, open the dialog box.
//---------------------------------------------------------------------------
LONG _export FAR PASCAL FlashPopupWndProc
(
HWND hwnd,
USHORT msg,
USHORT wp,
LONG lp
)
{
extern HANDLE hmodDLL;
switch (msg)
{
case WM_DESTROY:
fDlgInUse = FALSE;
break;
case WM_SHOWWINDOW:
if (wp)
{
PostMessage(hwnd, CM_OPENFLASHDLG, 0, 0L);
return 0L;
}
break;
case CM_OPENFLASHDLG:
VBDialogBoxParam(hmodDLL, "FlashDlg", (FARPROC)FlashDlgProc, 0L);
return 0L;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
//---------------------------------------------------------------------------
// An array mapping option buttons to RGB colors.
//---------------------------------------------------------------------------
long mpidcolor[] = { 0xff, 0xff00, 0xff0000 };
//---------------------------------------------------------------------------
// The Dialog Procedure for the FlashColor property dialog.
//---------------------------------------------------------------------------
BOOL FAR PASCAL _export FlashDlgProc
(
HWND hDlg,
USHORT msg,
USHORT wp,
LONG lp
)
{
switch (msg)
{
case WM_INITDIALOG:
{
RECT rect;
int nx, ny; // New x and y
int width, height;
int i;
LONG colorOld;
// Position dialog so it looks nice:
GetWindowRect(hDlg, &rect);
width = rect.right - rect.left;
height = rect.bottom - rect.top;
nx = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
ny = (GetSystemMetrics(SM_CYSCREEN) - height) / 3;
MoveWindow(hDlg, nx, ny, width, height, FALSE);
// Remember the old value of this property, so we can restore it
// on cancel:
if (VBGetControlProperty(hctlDialog, ipropDialog, &colorOld))
EndDialog(hDlg, FALSE);
// If the current color matches one of the option button colors,
// then set that option button:
for (i=0; i<sizeof(mpidcolor); i++)
if (mpidcolor[i] == colorOld)
CheckRadioButton(hDlg, DI_REDOPT, DI_BLUEOPT, i+DI_REDOPT);
// Save away colorOld so we can use it later
colorOldDialog = colorOld;
return TRUE;
}
case WM_COMMAND:
switch (wp)
{
case IDOK:
EndDialog(hDlg, TRUE);
return TRUE;
case IDCANCEL:
{
// Restore the old value, since we're canceling:
VBSetControlProperty(hctlDialog, ipropDialog, colorOldDialog);
EndDialog(hDlg, FALSE);
return TRUE;
}
case DI_REDOPT:
case DI_GREENOPT:
case DI_BLUEOPT:
{
CheckRadioButton(hDlg, DI_REDOPT, DI_BLUEOPT, wp);
VBSetControlProperty(hctlDialog, ipropDialog,
mpidcolor[wp-DI_REDOPT]);
return TRUE;
}
}
break;
}
return FALSE;
}
//---------------------------------------------------------------------------
// Register custom control. This routine is called by VB when the custom
// control DLL is loaded for use.
//---------------------------------------------------------------------------
BOOL FAR PASCAL _export VBINITCC
(
USHORT usVersion,
BOOL fRuntime
)
{
// Count the number of hosts using this VBX. A host can be vb.exe,
// any .exe compiled from vb which uses this custom control, or any
// other program which loads and uses VBX files.
++cVbxUsers;
// Register popup class if this is from the development environment.
if (!fRuntime && !fDevTimeInited)
{
WNDCLASS class;
class.style = 0;
class.lpfnWndProc = (FARPROC)FlashPopupWndProc;
class.cbClsExtra = 0;
class.cbWndExtra = 0;
class.hInstance = hmodDLL;
class.hIcon = NULL;
class.hCursor = NULL;
class.hbrBackground = NULL;
class.lpszMenuName = NULL;
class.lpszClassName = CLASS_FLASHPOPUP;
if (!RegisterClass(&class))
return FALSE;
// We successfully initialized the stuff we need at dev time
fDevTimeInited = TRUE;
}
// Register control(s)
if (usVersion <= VB100_VERSION)
return VBRegisterModel(hmodDLL, &modelCircle_Vb1);
if (usVersion <= VB200_VERSION)
return VBRegisterModel(hmodDLL, &modelCircle_Vb2);
else
return VBRegisterModel(hmodDLL, &modelCircle);
}
//---------------------------------------------------------------------------
// Unregister custom control. This routine is called by VB when the custom
// control DLL is being unloaded.
//---------------------------------------------------------------------------
VOID FAR PASCAL _export VBTERMCC
(
VOID
)
{
--cVbxUsers;
if (cVbxUsers == 0 && fDevTimeInited)
{
// Free any resources created for Dev environment
UnregisterClass(CLASS_FLASHPOPUP, hmodDLL);
}
return;
}
//---------------------------------------------------------------------------
// Provide custom control model information to host environment.
//---------------------------------------------------------------------------
LPMODELINFO FAR PASCAL _export VBGetModelInfo
(
USHORT usVersion
)
{
if (usVersion <= VB100_VERSION)
return &modelinfoCircle_Vb1;
if (usVersion <= VB200_VERSION)
return &modelinfoCircle_Vb2;
else
return &modelinfoCircle;
}
//---------------------------------------------------------------------------
// Initialize library. This routine is called when the first client loads
// the DLL.
//---------------------------------------------------------------------------
int FAR PASCAL LibMain
(
HANDLE hModule,
WORD wDataSeg,
WORD cbHeapSize,
LPSTR lpszCmdLine
)
{
// Avoid warnings on unused (but required) formal parameters
wDataSeg = wDataSeg;
cbHeapSize = cbHeapSize;
lpszCmdLine = lpszCmdLine;
hmodDLL = hModule;
return 1;
}
//---------------------------------------------------------------------------
// WEP
//---------------------------------------------------------------------------
// C7 and QCWIN provide default a WEP:
//---------------------------------------------------------------------------
#if (_MSC_VER < 610)
int FAR PASCAL WEP(int fSystemExit);
//---------------------------------------------------------------------------
// For Windows 3.0 it is recommended that the WEP function reside in a
// FIXED code segment and be exported as RESIDENTNAME. This is
// accomplished using the alloc_text pragma below and the related EXPORTS
// and SEGMENTS directives in the .DEF file.
//
// Read the comments section documenting the WEP function in the Windows
// 3.1 SDK "Programmers Reference, Volume 2: Functions" before placing
// any additional code in the WEP routine for a Windows 3.0 DLL.
//---------------------------------------------------------------------------
#pragma alloc_text(WEP_TEXT,WEP)
//---------------------------------------------------------------------------
// Performs cleanup tasks when the DLL is unloaded. WEP() is
// called automatically by Windows when the DLL is unloaded (no
// remaining tasks still have the DLL loaded). It is strongly
// recommended that a DLL have a WEP() function, even if it does
// nothing but returns success (1), as in this example.
//---------------------------------------------------------------------------
int FAR PASCAL WEP
(
int fSystemExit
)
{
// Avoid warnings on unused (but required) formal parameters
fSystemExit = fSystemExit;
return 1;
}
#endif // C6
//---------------------------------------------------------------------------